package com.cscec5b.inspection.service;

import com.cscec5b.inspection.config.AppProperties;
import com.cscec5b.inspection.dto.ReceiveDataPushDtos.*;
import com.cscec5b.inspection.entity.DetailInspectionOriginal;
import com.cscec5b.inspection.repository.DetailInspectionOriginalRepository;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StreamUtils;
import org.springframework.web.client.RestTemplate;

import java.net.URI;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Service
public class ReceiveDataPushService {

    private final DetailInspectionOriginalRepository detailRepo;
    private final AppProperties props;
    private final ObjectMapper om = new ObjectMapper();
    private final RestTemplate rt;

    private static final DateTimeFormatter TS_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    public ReceiveDataPushService(DetailInspectionOriginalRepository detailRepo,
                                  AppProperties props) {
        this.detailRepo = detailRepo;
        this.props = props;
        this.rt = buildRestTemplate(props);
    }

    @Transactional(readOnly = true)
    public PushResponse pushTask(Long taskId) {
        List<DetailInspectionOriginal> rows = detailRepo.findAllByTaskId(taskId);
        if (rows.isEmpty()) {
            PushResponse r = new PushResponse();
            r.code = "404"; r.msg = "未找到该 task 的数据"; r.detail = Map.of("task_id", taskId);
            return r;
        }

        List<DataItem> items = new ArrayList<>(rows.size());
        for (DetailInspectionOriginal r : rows) {
            DataItem d = new DataItem();
            d.task_id        = r.getTaskId();
            d.task_item_id   = r.getTaskItemId();
            d.inspection_data_id = r.getInspectionDataId();  // 应该是inspection_item_id
            d.data_type      = r.getDataType();
            d.fail_resample  = r.getFailResample();

            d.collector      = r.getCollector();
            d.inspect_part   = r.getInspectPart();
            d.part_type      = r.getPartType();

            d.check_amount   = r.getCheckAmount();
            d.passed_amount  = r.getPassedAmount();
            d.is_passed      = r.getIsPassed();
            d.check_record =(r.getCheckRecord() != null) ? ( r.getCheckRecord()) : null;

            // photos（单行只有一组拍摄信息，组织成数组；photo_url -> 读取并 base64）
            if (r.getPhotoUrl() != null && !r.getPhotoUrl().isBlank()) {
                Photo p = new Photo();
                p.capture_part = r.getPhotoCapturePart();
                p.capture_date = (r.getPhotoCaptureDate() == null) ? null : TS_FMT.format(r.getPhotoCaptureDate());
                p.data = safeReadAsBase64(r.getPhotoUrl()); // 关键：把文件转 base64
                d.photos = List.of(p);
            }

            // device_records & records字段：JSON 列，如果device_records为空，则不返回整个records字段
            if (r.getDeviceRecordsJson() != null && !r.getDeviceRecordsJson().isBlank()) {
//                d.records = parseRecords(r.getRecordsJson());
                d.device_records = (r.getDeviceRecordsJson() != null && !r.getDeviceRecordsJson().isBlank())
                        ? parseRecords(r.getDeviceRecordsJson())
                        : d.device_records;  // 暂时写到这个字段中，实际应该写到records字段
            }

            d.extra_report_number = (r.getExtraReportNumber() != null) ? (r.getExtraReportNumber()) : null;
            d.min_sample          = (r.getMinSample() != null) ? (r.getMinSample()) : null;

            items.add(d);
        }

        PushRequest body = new PushRequest();
        body.data = items;

        // 向上游系统发送数据
        String url = props.getUpstream().getBaseUrl() + props.getUpstream().getReceivePath();
        HttpHeaders hh = new HttpHeaders();
        hh.setContentType(MediaType.APPLICATION_JSON);
        hh.setAccept(List.of(MediaType.APPLICATION_JSON));
        hh.set("Authorization", "Bearer " + props.getUpstream().getToken());
        HttpEntity<PushRequest> req = new HttpEntity<>(body, hh);

        ResponseEntity<String> resp = rt.postForEntity(URI.create(url), req, String.class);

        // 封装成统一响应（也可直接返回对端原串）
        PushResponse out = new PushResponse();
        out.code = String.valueOf(resp.getStatusCodeValue());
        out.msg  = resp.getStatusCode().is2xxSuccessful() ? "推送成功" : "推送失败";
        out.detail = tryParse(resp.getBody());
        return out;
    }

    // ========= helpers =========

    private List<RecordItem> parseRecords(String json) {
        if (json == null || json.isBlank()) return null;
        try {
            return om.readValue(json, new TypeReference<List<RecordItem>>() {});
        } catch (Exception e) {
            // 容忍字符串数组或其它简单格式
            try {
                List<String> vals = om.readValue(json, new TypeReference<List<String>>() {});
                List<RecordItem> rs = new ArrayList<>();
                for (String v : vals) { RecordItem ri = new RecordItem(); ri.value = v; ri.is_passed = null; rs.add(ri); }
                return rs;
            } catch (Exception ex) {
                throw new IllegalArgumentException("records/device_records 解析失败");
            }
        }
    }

    private Object tryParse(String s) {
        if (s == null || s.isBlank()) return null;
        try { return om.readValue(s, Object.class); }
        catch (Exception e) { return s; }
    }

    private String safeReadAsBase64(String pathOrUrl) {
        try {
            byte[] bytes;
            if (pathOrUrl.startsWith("http://") || pathOrUrl.startsWith("https://")) {
                try (var in = new URL(pathOrUrl).openStream()) {
                    bytes = StreamUtils.copyToByteArray(in);
                }
            } else if (pathOrUrl.startsWith("file:")) {
                bytes = Files.readAllBytes(Paths.get(URI.create(pathOrUrl)));
            } else {
                // 普通本地绝对/相对路径
                bytes = Files.readAllBytes(Paths.get(pathOrUrl));
            }
            return Base64.getEncoder().encodeToString(bytes);
        } catch (Exception e) {
            // 读不到文件时可选择返回 null 或抛错；这里返回 null 并继续推送其它字段
            return null;
        }
    }

    private RestTemplate buildRestTemplate(AppProperties p) {
        var factory = new org.springframework.http.client.SimpleClientHttpRequestFactory();
        factory.setConnectTimeout(p.getUpstream().getConnectTimeoutMs());
        factory.setReadTimeout(p.getUpstream().getReadTimeoutMs());
        return new RestTemplate(factory);
    }
}
